package com.cskaoyan.javase.annotation._3handle;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * 注解处理器的实现(思路):
 *      1.首先通过反射获取这个注解
 *      2.获取注解当中的属性信息
 *      3.注解处理器执行相关的操作
 *
 * _@Retention元注解，作用是定义注解的保留级别，也就是注解的存活范围。分为以下三个级别：
 *      1.RetentionPolicy.RUNTIME：表示该注解会由JVM保留，因此运行时环境可以使用它，这样的一个注解才有可能影响代码执行。
 *      2.RetentionPolicy.CLASS：表示该注解在编译时由编译器保留，会进入class文件，但在类加载时期会被JVM忽略，不会进入虚拟机，不影响代码执行。一个注解如果没有显式用元注解@Retention声明保留级别，那么它默认的保留级别就是RetentionPolicy.CLASS。
 *
 *      3.RetentionPolicy.SOURCE：表示该注解仅保留在.java源文件级别中，会被编译器忽略掉。（类似于注释）
 *
 * @since 10:24
 * @author wuguidong@cskaoyan.onaliyun.com
 */
public class Test {
    public static void main(String[] args) throws ClassNotFoundException {
        // 以下模拟一个注解处理器
        // 1.获取Student类的Class对象
        Class<?> stuClazz = Class.forName("com.cskaoyan.javase.annotation._3handle.Student");
        // 2.通过Class对象获取修饰该类型的注解
        // 表示获取Student类上修饰该类型的注解类型A
        // 在获取某个注解类型之前,应该先判断一下是否有该类型的注解,如果有才去获取,如果没有就不获取了,避免空指针异常
        // boolean isAnnotationPresent(Class<? extends Annotation> annotationClass)
        // 如果指定类型的注释存在于此元素上，则返回 true，否则返回 false。
        if (stuClazz.isAnnotationPresent(A.class)) {
            // 有这个注解
            A annotation = stuClazz.getAnnotation(A.class);
            // 现在已经获取了注解类型信息,下面就获取注解体当中定义的属性的取值
            System.out.println(annotation.value());
        } else {
            System.out.println("该类型没有被注解A标记,获取不到该注解!");
        }
    }
}

@A(10000)
class Student {

}

// 该元注解表示这个注解A的保留级别是Runtime,表示它可以在程序运行期间生效
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@interface A {
    int value() default 666;
}

